﻿/************************************************************************

   Extended Silverlight Toolkit

   Copyright (C) 2010-2012 Xceed Software Inc.

   This program is provided to you under the terms of the Microsoft Public
   License (Ms-PL) as published at http://extendedsilverlight.codeplex.com/license

   Please purchase a commercial version of this toolkit if you are using
   it in a commercial product. The commercial versions support the project,
   and also include more features for each control, priority support,
   source code, updates, removed watermark, and a proprietary license.

   Visit http://xceed.com and follow @datagrid on Twitter.

  **********************************************************************/

using System;
using System.Windows;
using System.Windows.Media;

namespace Xceed.Silverlight.DataGrid
{
  internal abstract class WrapperBase : CustomBorder, IAnimatedLayoutElement, IRecyclable, IVisitorElement
  {
    public static readonly DependencyProperty AnimationXProperty = DependencyProperty.Register( "AnimationX", typeof( double ), typeof( WrapperBase ), new PropertyMetadata( 0d, WrapperBase.OnAnimationXChanged ) );
    public static readonly DependencyProperty AnimationYProperty = DependencyProperty.Register( "AnimationY", typeof( double ), typeof( WrapperBase ), new PropertyMetadata( 0d, WrapperBase.OnAnimationYChanged ) );

    protected WrapperBase( UIElement child )
    {
      if( child == null )
        throw new ArgumentNullException( "child" );

      this.Child = child;
      this.RenderTransform = new TranslateTransform();
    }

    public abstract object ReferenceItem
    {
      get;
    }

    public Rect? LastArrangeRect
    {
      get;
      set;
    }

    public double AnimationX
    {
      get
      {
        return ( double )GetValue( AnimationXProperty );
      }
      set
      {
        SetValue( AnimationXProperty, value );
      }
    }

    public double AnimationY
    {
      get
      {
        return ( double )GetValue( AnimationYProperty );
      }
      set
      {
        SetValue( AnimationYProperty, value );
      }
    }

    internal virtual bool IsRecycled
    {
      get
      {
        return ( this.Visibility == System.Windows.Visibility.Collapsed );
      }
      set
      {
        if( this.IsRecycled != value )
        {
          this.Visibility = ( value )
            ? System.Windows.Visibility.Collapsed
            : System.Windows.Visibility.Visible;
        }
      }
    }

    internal virtual object RecycleKey
    {
      get { return this.Child; }
    }

    private TranslateTransform TranslateTransform
    {
      get
      {
        return ( TranslateTransform )this.RenderTransform;
      }
    }

    protected virtual double CalculatePositionX()
    {
      return this.AnimationX;
    }

    protected virtual double CalculatePositionY()
    {
      return this.AnimationY;
    }

    protected void UpdatePositionX()
    {
      this.TranslateTransform.X = this.CalculatePositionX();
    }

    protected void UpdatePositionY()
    {
      this.TranslateTransform.Y = this.CalculatePositionY();
    }

    private static void OnAnimationXChanged( DependencyObject d, DependencyPropertyChangedEventArgs args )
    {
      WrapperBase w = ( WrapperBase )d;
      w.UpdatePositionX();
    }

    private static void OnAnimationYChanged( DependencyObject d, DependencyPropertyChangedEventArgs args )
    {
      WrapperBase w = ( WrapperBase )d;
      w.UpdatePositionY();
    }

    public virtual void PrepareBitmapCache()
    {
    }

    public virtual void ClearBitmapCache()
    {
    }

    protected virtual void LayoutMeasure( Size availableSize )
    {
      this.Measure( availableSize );
    }

    protected virtual void LayoutArrange( ArrangeParameters parameters )
    {
      Rect arrangeRect = parameters.ArrangePosition;

      if( parameters.LayoutParameters != null )
      {
        LayoutTransitionHelper.ArrangeAnimation( this, parameters.LayoutParameters.TransitionContext, parameters.ArrangePosition );
      }

      this.LastArrangeRect = arrangeRect;

      if( !double.IsNaN( this.Width ) )
      {
        arrangeRect.Width =  this.Width;
      }

      if( !double.IsNaN( this.Height ) )
      {
        arrangeRect.Height =  this.Height;
      }

      this.Arrange( arrangeRect );
    }

    #region IVisitorElement Members

    void IVisitorElement.Accept( IVisitor visitor )
    {
      this.Accept( visitor );
    }

    internal virtual void Accept( IVisitor visitor )
    {
      visitor.Visit( this );
    }

    #endregion

    #region ILayoutElement Members

    void ILayoutElement.Measure( Size availableSize )
    {
      this.LayoutMeasure( availableSize );
    }

    void ILayoutElement.Arrange( ArrangeParameters parameters )
    {
      this.LayoutArrange(parameters);
    }

    #endregion

    #region IRecyclable Members

    bool IRecyclable.IsRecycled
    {
      get
      {
        return this.IsRecycled;
      }
      set
      {
        this.IsRecycled = value;
      }
    }

    object IRecyclable.RecycleKey
    {
      get { return this.RecycleKey; }
    }

    #endregion

  }
}
